<?php
/**
 * @author: helei
 * @createTime: 2016-07-28 17:23
 * @description: 支付宝订单查询接口
 */

namespace Payment\Query;


use Payment\Common\Ali\AliBaseStrategy;
use Payment\Common\Ali\Data\BaseData;
use Payment\Common\Ali\Data\TradeQueryData;
use Payment\Common\PayException;
use Payment\Config;
use Payment\Utils\ArrayUtil;
use Payment\Utils\Curl;
use Payment\Utils\DataParser;

class AliTradeQuery extends AliBaseStrategy
{

    protected function getBuildDataClass()
    {
        return TradeQueryData::class;
    }
    
    protected function retData(array $data)
    {
        $url = parent::retData($data); // TODO: Change the autogenerated stub

        $ret = $this->request($url);

        return $this->createBackData($ret);
    }

    /**
     * 进行网络请求，获取订单查询结果
     * @param string $url
     * @return array
     *
     * ```php
     * $data =[
     *  'subject'   => 'subject', //
     *  'body'   => 'body',
     *  'amount'   => $'total_fee',
     *  'channel'   => Config::ALI,
     *  'order_no'   => 'out_trade_no',
     *  'buyer_id'   => 'buyer_email',
     *  'trade_state'   => $status,
     *  'transaction_id'   => 'trade_no',
     *  'time_end'   => 'gmt_payment',
     * ]
     * ```
     *
     * @throws PayException
     * @author helei
     */
    protected function request($url)
    {
        // 发起网络请求
        $curl = new Curl();
        $responseTxt = $curl->set([
            'CURLOPT_SSL_VERIFYPEER'    => true,
            'CURLOPT_SSL_VERIFYHOST'    => 2,
            'CURLOPT_CAINFO'    => $this->config->cacertPath,
            'CURLOPT_HEADER'    => 0,// 为了便于解析，将头信息过滤掉
        ])->get($url);

        if ($responseTxt['error']) {
            throw new PayException('网络发生错误，请稍后再试');
        }

        $body = $responseTxt['body'];

        // 格式化为数组
        if ($this->config->version && $this->config->format === 'JSON') {
            $retData = json_decode($body, true)['alipay_trade_query_response'];
        } else {
            $retData = DataParser::toArray($body);
            // 移除不必要参数
            $retData = ArrayUtil::removeKeys($retData, ['sign', 'sign_type', 'request']);
            $retData['response'] = $retData['response']['trade'];
        }

        return $retData;
    }

    /**
     * 处理支付宝返回的数据，统一处理后返回
     * @param array $data  支付宝返回的数据
     * @return array
     * @author helei
     */
    protected function createBackData(array $data)
    {

        if ($this->config->version) {
            // 新版本
            if ($data['code'] !== '10000') {
                return $retData = [
                    'is_success'    => 'F',
                    'error' => $data['sub_msg']
                ];
            }

            // 正确情况
            $retData = [
                'is_success'    => 'T',
                'response'  => [
                    'subject'   => '',
                    'body'   => '',
                    'amount'   => $data['total_amount'],
                    'receipt_amount' => $data['receipt_amount'],// 实收金额，单位为元，两位小数。
                    'pay_amount'    => $data['buyer_pay_amount'],// 改值可能不准
                    'point_amount' => $data['point_amount'],// 使用集分宝支付的金额
                    'fund_bill_list' => empty($data['fund_bill_list']) ? '' : $data['fund_bill_list'],// 支付成功的各个渠道金额信息
                    'channel'   => Config::ALI,
                    'order_no'   => $data['out_trade_no'],
                    'buyer_id'   => $data['buyer_logon_id'],
                    'trade_state'   => $this->getTradeStatus($data['trade_status']),
                    'transaction_id'   => $data['trade_no'],
                    'time_end'   => $data['send_pay_date'],
                ],
            ];

            return $retData;
        }


        if ($data['is_success'] === 'F') {
            return $retData = [
                'is_success'    => 'F',
                'error' => $data['error']
            ];
        }

        // 正确情况
        $retData = [
            'is_success'    => 'T',
            'response'  => [
                'subject'   => $data['response']['subject'],
                'body'   => isset($data['response']['body']) ? $data['response']['body'] : '',
                'amount'   => $data['response']['total_fee'],
                'channel'   => Config::ALI,
                'order_no'   => $data['response']['out_trade_no'],
                'buyer_id'   => $data['response']['buyer_email'],
                'trade_state'   => $this->getTradeStatus($data['response']['trade_status']),
                'transaction_id'   => $data['response']['trade_no'],
                'time_end'   => $data['response']['gmt_payment'],
            ],
        ];

        return $retData;
    }
}